package com.whfc.openapi.api.fvs.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.whfc.common.constant.QueueConst;
import com.whfc.common.third.uni.UniProperties;
import com.whfc.common.util.JSONUtil;
import com.whfc.fim.entity.FimAlgResult;
import com.whfc.fim.entity.FimWarnRule;
import com.whfc.fim.param.FimAlgResultParam;
import com.whfc.fim.service.FimResultService;
import com.whfc.fim.service.FimWarnRuleService;
import com.whfc.fvs.dto.FvsDeviceDTO;
import com.whfc.fvs.service.FvsDeviceService;
import com.whfc.openapi.api.fvs.dto.UniEvent;
import com.whfc.openapi.api.fvs.service.UniCallbackService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 宇视回调服务实现类
 */
@Slf4j
@Service
public class UniCallbackServiceImpl implements UniCallbackService {

    @DubboReference(interfaceClass = FimResultService.class, version = "1.0.0")
    private FimResultService fimResultService;
    @DubboReference(interfaceClass = FimWarnRuleService.class, version = "1.0.0")
    private FimWarnRuleService fimWarnRuleService;
    @DubboReference(interfaceClass = FvsDeviceService.class, version = "1.0.0")
    private FvsDeviceService fvsDeviceService;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private UniProperties uniProperties;


    @Override
    public void handleEvent(UniEvent eventData) {
        log.debug("处理宇视报警事件: {}", JSONObject.toJSONString(eventData));

        try {

            Integer type = uniProperties.getTypeMapper().get(eventData.getEventType());
            if (type == null){
                log.error("处理宇视报警事件失败: 报警类型 {} 未知", eventData.getEventType());
                return;
            }

            // 3. 创建报警记录并保存到系统
            FvsDeviceDTO fvsDeviceDTO = fvsDeviceService.selectBySn(eventData.getSrcIndexCode());
            if (fvsDeviceDTO == null){
                log.error("处理宇视报警事件失败: {} 无效", eventData.getSrcIndexCode());
                return;
            }

            FimWarnRule rule = getWarmRule(eventData);

            setAiWarnInfo(eventData, fvsDeviceDTO, rule);
        } catch (Exception e) {
            log.error("处理宇视报警事件失败: {}", e.getMessage(), e);
            // throw new BizException("处理宇视报警事件失败: " + e.getMessage());
        }
    }

    private FimWarnRule getWarmRule(UniEvent eventData) {
        FimWarnRule query = new FimWarnRule();
        query.setDeptId(uniProperties.getDeptId());
        query.setType(uniProperties.getTypeMapper().get(eventData.getEventType()));
        List<FimWarnRule> ruleList = fimWarnRuleService.select(query);
        if (ruleList == null || ruleList.isEmpty()) {
            FimWarnRule rule = new FimWarnRule();
            rule.setName(eventData.getEventType());
            rule.setType(uniProperties.getTypeMapper().get(eventData.getEventType()));
            rule.setDeptId(uniProperties.getDeptId());
            rule.setDelFlag(0);
            rule.setCreateTime(new Date());
            rule.setUpdateTime(new Date());
            fimWarnRuleService.save(rule);
            ruleList = fimWarnRuleService.select(query);
        }
        return ruleList.isEmpty()?null:ruleList.get(0);
    }

    /**
     * 算法报警上报
     * @param eventData
     * @param fvsDevice
     */
    private void setAiWarnInfo(UniEvent eventData, FvsDeviceDTO fvsDevice, FimWarnRule rule) {
        FimAlgResultParam fimAlgResultParam = new FimAlgResultParam();
        fimAlgResultParam.setDeptId(fvsDevice.getDeptId());
        fimAlgResultParam.setDeviceId(fvsDevice.getId());
        fimAlgResultParam.setDeviceName(fvsDevice.getName());
        fimAlgResultParam.setDeviceVendor(fvsDevice.getVendor());
        fimAlgResultParam.setAlgCheckType(rule.getType());
        fimAlgResultParam.setAlgCheckTypeName(rule.getName());
        fimAlgResultParam.setTime(parseAlarmTime(eventData.getHappenTime()));
        if (eventData.getImageUrl() != null){
            List<String> images = new ArrayList<>();
            String url = uniProperties.getPreUrlImage() + eventData.getImageUrl();
            url = url.replaceAll("\\?.*", "");
            images.add(url);
            fimAlgResultParam.setAlgResultImgList(images);
        }
        //推送数据
        amqpTemplate.convertAndSend(QueueConst.FIM_RESULT, JSONUtil.toString(fimAlgResultParam));
    }


    @Override
    public void handleAlarmEvent(UniEvent eventData) {
        log.info("处理宇视报警事件: {}", JSONObject.toJSONString(eventData));
    }

    @Override
    public void handleDeviceStatusEvent(UniEvent eventData) {
        log.info("处理宇视设备状态事件: {}", JSONObject.toJSONString(eventData));

    }

    @Override
    public void handleVideoLossEvent(UniEvent eventData) {
        log.info("处理宇视视频丢失事件: {}", JSONObject.toJSONString(eventData));

        // 视频丢失事件可以视为一种特殊的报警事件
        handleAlarmEvent(eventData);
    }

    @Override
    public void handleMotionDetectionEvent(UniEvent eventData) {
        log.info("处理宇视移动侦测事件: {}", JSONObject.toJSONString(eventData));

        // 移动侦测事件可以视为一种特殊的报警事件
        handleAlarmEvent(eventData);
    }

    @Override
    public void handleUnknownEvent(UniEvent eventData) {
        log.warn("处理未知宇视事件: {}", JSONObject.toJSONString(eventData));

        // 对于未知事件，记录日志并尝试作为通用报警事件处理
        log.warn("收到未知类型的宇视事件，事件数据: {}", JSONObject.toJSONString(eventData));
    }

    /**
     * 解析设备ID（将宇视设备ID转换为系统设备ID）
     */
    private FvsDeviceDTO parseDeviceId(String srcIndexCode) {
        try {
            return fvsDeviceService.selectBySn(srcIndexCode);
        } catch (Exception e) {
            log.error("解析设备ID失败: {}", e.getMessage());
            return null; // 返回默认设备ID
        }
    }

    /**
     * 解析报警时间
     */
    private Date parseAlarmTime(String happenTime) {
        try {
            return Date.from(Instant.parse(happenTime));
        } catch (Exception e) {
            log.error("解析报警时间失败，使用当前时间: {}", e.getMessage());
            return new Date();
        }
    }

    /**
     * 根据设备ID获取组织机构ID
     */
    private Integer getDeptIdByDeviceId(Integer deviceId) {
        // 这里需要根据设备ID查询对应的组织机构ID
        // 暂时返回默认值，实际应用中需要实现组织机构查询逻辑
        return 1; // 默认组织机构ID
    }

    /**
     * 保存报警记录到系统
     */
    private void saveAlarmRecord(FimAlgResult alarmRecord) {
        try {
            // 使用FimAlgResultMapper保存报警记录
            // 这里需要调用FimResultService的相关方法
            log.info("保存报警记录: 设备={}, 类型={}, 时间={}",
                    alarmRecord.getDeviceName(),
                    alarmRecord.getAlgCheckTypeName(),
                    alarmRecord.getTime());

//            fimResultService.detail();

        } catch (Exception e) {
            log.error("保存报警记录失败: {}", e.getMessage(), e);
//            throw new BizException("保存报警记录失败: " + e.getMessage());
        }
    }



}